<template>
    <div class="office-viewer-container">
        <div class="viewer-header">
            <h2>Office 文档在线预览</h2>
            <div class="upload-section">
                <el-upload
                    ref="uploadRef"
                    :auto-upload="false"
                    :on-change="handleFileChange"
                    :show-file-list="false"
                    accept=".doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf"
                    drag
                >
                    <el-icon class="el-icon--upload"><upload-filled /></el-icon>
                    <div class="el-upload__text">
                        将文件拖到此处，或<em>点击上传</em>
                    </div>
                    <template #tip>
                        <div class="el-upload__tip">
                            支持 .doc, .docx, .xls, .xlsx, .ppt, .pptx, .pdf 格式文件
                        </div>
                    </template>
                </el-upload>
            </div>
      
            <div class="demo-files">
                <h3>演示文件</h3>
                <div class="demo-buttons">
                    <el-button 
                        v-for="file in demoFiles" 
                        :key="file.name"
                        @click="loadDemoFile(file)"
                        type="primary"
                        size="small"
                    >
                        {{ file.name }}
                    </el-button>
                </div>
            </div>

            <div class="service-selector">
                <h3>预览服务</h3>
                <el-radio-group v-model="selectedService" @change="switchService">
                    <el-radio-button 
                        v-for="service in viewerServices" 
                        :key="service.value"
                        :label="service.value"
                    >
                        {{ service.label }}
                    </el-radio-button>
                </el-radio-group>
                <div class="service-description">
                    {{ viewerServices.find(s => s.value === selectedService)?.description }}
                </div>
            </div>
        </div>

        <div v-if="currentFile" class="viewer-content">
            <div class="file-info">
                <el-tag :type="getFileTypeInfo(currentFile.name).color">
                    {{ getFileTypeInfo(currentFile.name).name }}
                </el-tag>
                <span class="file-name">{{ currentFile.name }}</span>
                <span class="file-size" v-if="currentFile.size">
                    {{ formatFileSize(currentFile.size) }}
                </span>
                <el-button @click="closeViewer" type="danger" size="small">
                    关闭预览
                </el-button>
            </div>
      
            <div class="viewer-frame">
                <iframe
                    v-if="viewerUrl"
                    :src="viewerUrl"
                    frameborder="0"
                    width="100%"
                    height="100%"
                    allowfullscreen
                ></iframe>
                <div v-else class="loading-placeholder">
                    <el-icon class="is-loading"><loading /></el-icon>
                    <p>正在加载文档预览...</p>
                </div>
            </div>
        </div>

        <div v-else class="empty-state">
            <el-empty description="请选择要预览的文档">
                <el-button type="primary">选择文件</el-button>
            </el-empty>
        </div>
    </div>
</template>

<script setup lang="ts">
import { ref, onUnmounted } from 'vue';
import { ElMessage } from 'element-plus';
import { UploadFilled, Loading } from '@element-plus/icons-vue';
import OfficeViewer, { FileUploader } from '@/utils/officeViewer';
import type { FileInfo } from '@/utils/officeViewer';

const uploadRef = ref();
const currentFile = ref<FileInfo | null>(null);
const viewerUrl = ref('');
const selectedService = ref('microsoft');
const objectUrls = ref<string[]>([]);

// 创建Office预览器实例
const officeViewer = new OfficeViewer({ service: 'microsoft' });

// 演示文件列表
const demoFiles = ref<FileInfo[]>([
    {
        name: '示例Word文档',
        type: 'docx',
        url: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf'
    },
    {
        name: '示例Excel表格',
        type: 'xlsx',
        url: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf'
    },
    {
        name: '示例PPT演示',
        type: 'pptx',
        url: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf'
    }
]);

// 获取预览服务选项
const viewerServices = OfficeViewer.getViewerServices();

// 获取文件类型信息
const getFileTypeInfo = (fileName: string) => {
    return OfficeViewer.getFileTypeInfo(fileName);
};

// 处理文件选择
const handleFileChange = (file: any) => {
    // 验证文件
    const validation = FileUploader.validateFile(file.raw);
    if (!validation.valid) {
        ElMessage.error(validation.message || '文件验证失败');
        return;
    }

    // 创建本地文件URL用于预览
    const objectUrl = FileUploader.createObjectURL(file.raw);
    objectUrls.value.push(objectUrl);

    // 生成预览URL
    const viewerUrl = officeViewer.generateViewerUrl(objectUrl);
  
    currentFile.value = {
        name: file.name,
        type: file.name.split('.').pop()?.toLowerCase() || '',
        url: objectUrl,
        size: file.size
    };
  
    loadDocument(viewerUrl);
};

// 加载演示文件
const loadDemoFile = (file: FileInfo) => {
    currentFile.value = file;
    const viewerUrl = officeViewer.generateViewerUrl(file.url);
    loadDocument(viewerUrl);
};

// 加载文档
const loadDocument = (url: string) => {
    viewerUrl.value = url;
    ElMessage.success('文档加载成功');
};

// 关闭预览
const closeViewer = () => {
    currentFile.value = null;
    viewerUrl.value = '';
};

// 切换预览服务
const switchService = (service: string) => {
    selectedService.value = service;
    officeViewer.updateConfig({ service: service as any });
  
    if (currentFile.value) {
        const newViewerUrl = officeViewer.generateViewerUrl(currentFile.value.url);
        loadDocument(newViewerUrl);
    }
};

// 格式化文件大小
const formatFileSize = (bytes: number): string => {
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};

// 组件卸载时清理资源
onUnmounted(() => {
    objectUrls.value.forEach(url => {
        FileUploader.revokeObjectURL(url);
    });
});
</script>

<style scoped lang="less">
.office-viewer-container {
  max-width: 1200px;
  padding: 20px;
  margin: 0 auto;
}

.viewer-header {
  margin-bottom: 30px;
  
  h2 {
    margin-bottom: 20px;
    color: #333;
  }
}

.upload-section {
  margin-bottom: 30px;
  
  :deep(.el-upload-dragger) {
    width: 100%;
    height: 180px;
  }
}

.demo-files {
  margin-top: 20px;
  
  h3 {
    margin-bottom: 15px;
    font-size: 16px;
    color: #666;
  }
  
  .demo-buttons {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
  }
}

.service-selector {
  margin-top: 20px;
  
  h3 {
    margin-bottom: 15px;
    font-size: 16px;
    color: #666;
  }
  
  .service-description {
    margin-top: 10px;
    font-size: 14px;
    color: #999;
  }
}

.viewer-content {
  overflow: hidden;
  border: 1px solid #e4e7ed;
  border-radius: 8px;
}

.file-info {
  display: flex;
  align-items: center;
  gap: 15px;
  padding: 15px 20px;
  background-color: #f5f7fa;
  border-bottom: 1px solid #e4e7ed;
  
  .file-name {
    flex: 1;
    font-weight: 500;
    color: #333;
  }
  
  .file-size {
    font-size: 14px;
    color: #999;
  }
}

.viewer-frame {
  position: relative;
  height: 600px;
  
  iframe {
    width: 100%;
    height: 100%;
    border: none;
  }
}

.loading-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: #909399;
  
  .el-icon {
    margin-bottom: 10px;
    font-size: 32px;
  }
  
  p {
    margin: 0;
    font-size: 14px;
  }
}

.empty-state {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 400px;
}
</style> 